package com.qf.spring2202.customfactory.utils;

import com.qf.spring2202.customfactory.service.UserService;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * 自定义工程
 * 职责：
 * 1. 读取 classpath 下的配置文件 beans.properties
 * 2. 提供一个可以获取对象的方法 ，  getBean(String name)
 */
public class MyFactory {


    private String configFilePath ;  // 配置文件在classpath下的 文件名

    // 该实例属性用于保存解析后的配置文件中的内容
    private Properties properties = new Properties();


    // 该工程的对象缓存
    private Map<String,Object> cache = new HashMap<>();


    /**
     * 如果不传配置文件名的话，默认的配置文件名为 beans.properties
     */
    public MyFactory() throws IOException {
        // 调用 单参构造函数
        this("/beans.properties");
    }

    /**
     *
     * @param configFilePath 注意，参数需要以 / 开头
     * @throws IOException
     */
    public MyFactory(String configFilePath) throws IOException {
        this.configFilePath = configFilePath;

        // 配置文件 ---->  InputStream
        final InputStream inputStream = getClass().getResourceAsStream(configFilePath);

        // 把输入留中的内容，转换成 properties 对象中的信息 ，完成properties的初始化
        properties.load(inputStream);
    }


    /**
     * 获取对像的方法
     * @param beanName 对象的标识符
     * @return 返回一个 可用的对象
     */
    public Object getBean(String beanName) throws IllegalAccessException, InstantiationException, ClassNotFoundException {

        //0. 先检查 工程的缓存中是否有该标识对应的对象 ，如果有，则直接返回
        Object obj = cache.get(beanName);

        if (obj!=null){
            return obj;
        }

        //1. 根据 beanName 获取所需bean的类的全限定名
        final String clazzname = properties.getProperty(beanName);

        //2. 根据类的全限定名创建对象
        obj = createObject(clazzname);

        //3. 把对象放入缓存
        if (obj!=null){
            cache.put(beanName,obj);
        }

        //4. 返回对象
        return obj;


    }

    /**
     * 反射创建对象
     * @param clazzname 对象的全限定名
     * @return
     */
    private Object createObject(String clazzname) throws ClassNotFoundException, IllegalAccessException, InstantiationException {

        //1. 加载Class
        final Class<?> clazz = Class.forName(clazzname);

        //2. 反射创建对象
        final Object o = clazz.newInstance();

        return o;
    }

    public static void main(String[] args) throws IOException, IllegalAccessException, ClassNotFoundException, InstantiationException {
        //1. 创建工作对象
        final MyFactory myFactory = new MyFactory();

        //2. 使用工作对象，获取需要的业务对象
        final UserService userService = (UserService) myFactory.getBean("userService");

        //3. 使用业务对象
        System.out.println(userService.getUser(200));
    }

}
